package com.ecar.api.rest.filter;

import com.ecar.api.support.util.Redis;
import com.ecar.common.cipher.MD5;
import com.ecar.common.util.HttpUtils;

import org.apache.poi.util.SystemOutLogger;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.filter.OncePerRequestFilter;

import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

/**
 * 添加跨域许可，过滤并记录请求
 * Created by admin
 */
public class RestFilter extends OncePerRequestFilter {

	private static final Logger log = LoggerFactory.getLogger(RestFilter.class);

	@Override
	protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain)
			throws ServletException, IOException {
		if (!request.getMethod().matches("^GET|get|POST|post|PUT|put|DELETE|delete|OPTIONS|options$")) {
			log.debug("Unsupported Method: " + request.getMethod());
			log.debug("Uri: " + request.getRequestURI());
			response.sendError(405, "Method Not Allowed");
			return;
		}

		response.addHeader("Access-Control-Allow-Origin", "*");
		response.addHeader("Access-Control-Allow-Credentials", "true");
		response.addHeader("Access-Control-Allow-Methods", "GET, POST, DELETE, PUT, OPTIONS");
		response.addHeader("Access-Control-Allow-Headers", "X-Requested-With, Content-Type, Accept");

		log.info("{} URI: {} [{}]", request.getMethod(),
				 request.getRequestURI(), request.getParameter("access_token"));
		if (tooSoon(request)) {
			response.sendError(423, "Too soon. Processing your request.");
			return;
		}

		filterChain.doFilter(request, response);
	}

	private boolean isWhiteList(String uri) {
		return uri.matches("^/api/r/wx/h5$");
	}

	/**
	 * 检查请求是否过快
	 * @param request
	 * @return
	 */
	private boolean tooSoon(HttpServletRequest request) {
		boolean tooSoon = false;
		MD5 md5 = new MD5();
		String uri = request.getRequestURI();
		String token = request.getParameter("access_token");
		String ip = HttpUtils.getRemoteHost(request);
		String method = request.getMethod();
		String key = md5.getMD5ofStr(ip+token+method+uri);

		long pttl;
		if (isWhiteList(uri)) {
			return tooSoon;
		} else if (isHighlyRestricted(uri)) {
			pttl = 1000;
		} else if (isHighlyRestrictedForRefund(uri)){
			pttl = 5000;
		}else {
			pttl = 100;
			//pttl = 300;
		}

		if(Redis.c.exists(Redis.K.REQ_FILTER.to(key))) tooSoon = true;
		Redis.c.psetex(Redis.K.REQ_FILTER.to(key), pttl, "1");
		return tooSoon;
	}

	/**
	 * 所以数据新增接口、订单下单/退款接口，调起支付接口
	 * @param uri
	 * @return
	 */
	private boolean isHighlyRestricted(String uri) {
		return uri.matches("^/api/r/(order/\\w+/\\d+/(submit))|(.+/insert)|(pay/\\d+/.+)|(pub/shift)$");
	}
	
	private boolean isHighlyRestrictedForRefund(String uri) {
		//return uri.matches("^/api/r/(order/\\w+/\\d+/(submit|refund))|(.+/insert)|(pay/\\d+/.+)|(pub/shift)$");
		return uri.matches("^/api/r/(order/\\w+/\\d+/(refund))$");
	}

}
